#include <regx52.h>
#include "oled.h"
#include "Delay.h"
#include "Timer0.h"
#include "I2C.h"
#include "Digital_tube.h"


//数据校验成功标志位
bit Data_Validation_Success_Flag=0;

//7位从机地址	最低位统一为零填充读写标志
unsigned char slave_address = 0xAA;
//7位主机地址
unsigned char master_address = 0xAE;

unsigned char command = 0x00;




/*
注意:从机无权控制时钟总线(SCL)
从机在时钟线低电平时准备数据,时钟线高电平时数据不能变
依次将数据放入SDA线上（高位在前）

在SCL高电平是接收数据
在SCL低电平时发送数据
*/





/**
  * @brief  奇校验 如果字节中的1是奇数返回1，否则返回0
  * @param  校验的字节码
  * @retval 无
  */
bit calculate_parity(unsigned char Byte) {
	unsigned char i;
    bit parity = 0;
    for(i = 0; i < 8; i++) {
        parity ^= (Byte & (0x80 >> i)) ? 1 : 0;
    }
    return parity;
}



/**
  * @brief  发送一个位
  * @param  bit
  * @retval 无
  */
void send_bit(bit parity) {
    I2C_SCL = 0;
    I2C_SDA = parity;
    I2C_SCL = 1;
    I2C_SCL = 0;
}



/**
  * @brief  判断校验位并发送
  * @param  无
  * @retval 无
  */
void send_parity_bit(unsigned char Byte) {
	send_bit(calculate_parity(Byte));
}





/**
  * @brief  接受并判断校验位
  * @param  无
  * @retval 无
  */
bit receive_parity_bit(unsigned char Byte) {
    bit received_parity;
    bit calculated_parity = calculate_parity(Byte);

    // 读取奇校验位
    while (I2C_SCL == 0);
    received_parity = I2C_SDA;
    while (I2C_SCL);

    // 验证奇校验位
    if (calculated_parity != received_parity) {
        // 奇校验错误处理
        // 这里可以添加错误处理逻辑
        return 0; // 返回0表示奇校验错误
    }

    return 1; // 返回1表示奇校验正确
}









//从机功能函数 接收一个字节
unsigned char slave_receive_Byte() {
	unsigned char i,Byte=0;
	for(i=0;i<8;){
		while (I2C_SCL);
		while (I2C_SCL==0);	//在时序的高电平读取
		Byte = (Byte << 1) | I2C_SDA;
		++i;
		OLED_ShowBinNum(3,1,Byte,8);
	}
	return Byte;
}





//从机功能函数 发送一个字节  确保SDA总线以及被主机释放(主机拉高SDA)
void slave_send_Byte(unsigned char Byte) {
	unsigned char i;
	for(i=8;i>0;){
		//从高位到低写入
		if(I2C_SCL == 0){
			I2C_SDA = (Byte | (0x01<<(i-1))) ? 1 : 0;
			--i;
		}
		//等待SCL变为高电平,到下一个脉冲
		while (I2C_SCL == 0);
		//等待主机处理完成,在此高电平期间SDA保持
		while (I2C_SCL == 1);
	}
}




//从机功能函数 从机发送应答 (主机应释放SDA)
void slave_SendAck(bit AckBit) {
	// 在SCL低电平时准备应答信号
	if(I2C_SCL==0) I2C_SDA = AckBit;
	// while (I2C_SCL==0);
	// while (I2C_SCL);
    I2C_SDA = 1;          // 释放 SDA
}




// 从机功能函数 从机接收应答
bit slave_ReceiveAck() {
	bit AckBit;
	while (I2C_SCL);
	while (I2C_SCL == 0);
    AckBit = I2C_SDA; // 读取应答信号
	return AckBit;
}





//从机等待开始位
void slave_wait_start() {
    while(1) {
        // 持续监测起始条件
        while(I2C_SCL == 1 && I2C_SDA == 1); // 等待SDA=1且SCL=1的初始状态

        // 检测下降沿：当SDA从高变低且SCL保持高
        while(I2C_SCL == 1) {
            if(I2C_SDA == 0) {
                return; // 成功检测到起始条件
            }
        }
    }
}


void master(){
	unsigned char i,Byte=0x01,time=5000,index=0;
	unsigned char Bytes[10] = {0,1,2,3,4,5,6,7,8,9};
	P0 = 1;

	I2C_Start();
	while (1)
	{	
		I2C_SCL=0;
		for(i=0;i<8;i++){
			I2C_SDA = Bytes[index]&(0x80>>i);
			Delayms(time);
			I2C_SCL=1;
			Delayms(time);
			I2C_SCL=0;
			Delayms(time);
		}

		if(++index > 9) {
			index = 0;

		}

		while(I2C_ReceiveAck());

	}
}




void slave(){
	unsigned char num;
	OLED_Init();
	OLED_ShowString(1,1,"SCL:");
	OLED_ShowString(1,8,"SDA:");
	OLED_ShowString(2,1,"address:");
	OLED_ShowNum(1,5,I2C_SCL,1);
	OLED_ShowNum(1,12,I2C_SDA,1);
	slave_wait_start();
	while (1)
	{
		num = slave_receive_Byte();
		//发送应答 成功回复0
		slave_SendAck(0);
		OLED_ShowNum(2,9,num,3);
	}
}


#ifdef SLAVE
void main(){
	slave();
}
#else
void main(){
	master();
}
#endif
